<?php
declare(strict_types = 1);
namespace Haozing\FastCore\Aspect;

use Haozing\FastCore\Annotation\Role;
use Haozing\FastCore\Context\UserContext;
use Haozing\FastCore\Exception\NoPermissionException;
use Haozing\FastCore\Interfaces\AuthUserInterface;
use Haozing\FastCore\Utils\Auth\PermissionCheck;
use Haozing\FastCore\Utils\Request\Request;
use Hyperf\Di\Annotation\Aspect;
use Hyperf\Di\Aop\AbstractAspect;
use Hyperf\Di\Aop\ProceedingJoinPoint;
use Hyperf\Di\Exception\Exception;

/**
 * Class RoleAspect
 */
#[Aspect]
class RoleAspect extends AbstractAspect
{
    public array $annotations = [
        Role::class
    ];

    protected AuthUserInterface $authUser;

    protected Request $request;

    public function __construct(
        AuthUserInterface $authUser,
        Request $request,
    )
    {
        $this->authUser = $authUser;
        $this->request = $request;
    }
    /**
     * @param ProceedingJoinPoint $proceedingJoinPoint
     * @return mixed
     * @throws Exception
     */
    public function process(ProceedingJoinPoint $proceedingJoinPoint)
    {
        if (isset($proceedingJoinPoint->getAnnotationMetadata()->method[Role::class])) {
            $role = $proceedingJoinPoint->getAnnotationMetadata()->method[Role::class];
        }

        // 没有使用注解，则放行
        if (empty($role->code)) {
            return $proceedingJoinPoint->process();
        }
        // 从上下文中获取用户信息
        $user = UserContext::getOrNull();

        // 如果是超管放行
        if ($user && $user->get('is_super_admin', 0) == 1) {
            return $proceedingJoinPoint->process();
        }

        if (!$user || !$user->all()) {
            throw new NoPermissionException($this->request->getPathInfo().'没有用户信息');
        }

        $this->checkRole($user->all(),$role->code, $role->where);

        return $proceedingJoinPoint->process();
    }

    /**
     * 检查角色.
     */
    protected function checkRole(array $user, string $codeString, string $where): bool
    {
        //调用接口获取用户权限code
        $roles = $this->authUser->getRoleCodes($user);
        if ($where === 'OR') {
            foreach (explode(',', $codeString) as $code) {
                if (in_array(trim($code), $roles)) {
                    return true;
                }
            }
            throw new NoPermissionException($this->request->getPathInfo().'-'.$codeString.'-'.'没有权限');
        }

        if ($where === 'AND') {
            foreach (explode(',', $codeString) as $code) {
                $code = trim($code);
                if (! in_array($code, $roles)) {
                    throw new NoPermissionException($this->request->getPathInfo().'-'.$code.'-'.'没有权限');
                }
            }
        }

        return true;
    }
}